import json
import os
import re
import shutil

from Tree_Node import TreeNode
from expect_check import get_function_content

g_notfind_file = {}

def get_deps_from(file, targets):
    try:
        targets_pattern = "|".join(re.escape(target) for target in targets)
        pattern = re.compile(rf'[a-zA-Z_]\("({targets_pattern})"\)')
        groups = get_function_content(file, pattern)
    except Exception as e:
        g_notfind_file[file] = list(targets)
        return None

    result = set()
    deps_pattern = re.compile(r'\n\s*deps\s*(=|\+=)\s*\[([^\]]+)\]', re.DOTALL)
    sources_pattern = re.compile(r'\n\s*sources\s*(=|\+=)\s*\[([^\]]+)\]', re.DOTALL)
    for group_info in groups:
        # 去除注释
        group_info = re.sub(r'#.*', '', group_info)
        deps_matches = re.findall(deps_pattern, group_info)
        sources_matches = re.findall(sources_pattern, group_info)
        for match in deps_matches + sources_matches:
            lines = match[1].replace('\n', '').split(',')
            for line in lines:
                line = line.replace("'", "").replace('"', '').strip()
                if len(line) == 0 or line.startswith("$") or line.startswith("//") or line.startswith('./'):
                    continue
                result.add(line)
    return result

def get_start_targets(file,xts_type):
    xts_root = {
        'acts':'ACTS_ROOT',
        'dcts':'DCTS_ROOT',
        'hats':'HATS_ROOT',
        'hits':'HITS_ROOT'
    }
    target_fields = [
        '_all_test_packages',
        '_all_test_packages_ivi',
        '_all_test_packages_intellitv',
        '_all_test_packages_wearable'
    ]
    with open(file, "r", encoding="utf-8") as f:
        content = f.read()
    # 去除注释
    code_without_comments = re.sub(r'#.*', '', content)

    # 匹配所有 = [] 结构，包括 = 前的变量名
    matches = re.findall(r'(\w+)\s*=\s*\[([^]]+)\]', code_without_comments)

    result = set()
    for var_name, match in matches:
        if var_name in target_fields:
            # 分割每行内容
            lines = match.replace('\n','').split(',')
            for line in lines:
                line = line.replace("'","").replace('"','').replace("${"+xts_root[xts_type]+"}",'').strip()
                if len(line) == 0:
                    continue
                result.add(line)

    return list(result)

def build_tree(node):
    path = node.get_path_from_root()
    targets = set()
    targets_a = set(node.targets)
    while targets_a.difference(targets):
        build_path = f"{path}/BUILD.gn"
        deps = get_deps_from(build_path, targets_a - targets)
        if deps:
            node.add_children_by_paths(deps)
            node.visit_flag = True
        targets = targets_a
        targets_a = set(node.targets)
    for name, c_node in list(node.children.items()):
        build_tree(c_node)


def find_extra_directories(actual_root, tree_root, differences):
    """查找实际存在但树中未记录的目录"""
    # 树中的子目录:
    children_tree = tree_root.children
    # 实际路径子目录:
    children_actual = os.listdir(actual_root)
    # 跳过的情况
    if "signature" in children_actual or "Test.json" in children_actual:
        return
    for path in children_actual:
        full_path = os.path.join(actual_root, path)
        # 跳过的情况
        if os.path.isfile(full_path) or "lite" in path or path.startswith('.'):
            continue
        if path in children_tree:
            find_extra_directories(full_path, children_tree[path], differences)
        else:
            differences.append(f"{full_path}")


def move_differences(project_root, differences):
    dest_dir = './out'
    results = {
        'success': [],
        'skipped': [],
        'errors': []
    }
    try:
        os.makedirs(dest_dir, exist_ok=True)
    except Exception as e:
        results['errors'].append(f"创建目标目录失败: {str(e)}")
        return results

    for src_path in differences:
        try:
            # 验证源路径有效性
            if not os.path.exists(src_path):
                results['errors'].append(f"源目录不存在: {src_path}")
                continue
            # 构建目标路径
            dir_name = os.path.relpath(src_path, project_root)
            dest_path = os.path.join(dest_dir, dir_name)

            # 执行移动操作
            shutil.move(src_path, dest_path)
            results['success'].append({
                'source': src_path,
                'destination': dest_path
            })
        except Exception as e:
            results['errors'].append(f"移动 {src_path} 失败: {str(e)}")

    return results


def del_uncompile(project_root, xts_type, is_del):
    # 项目起始路径
    root = TreeNode(project_root)
    file_list = get_start_targets(f"{project_root}/test_packages.gni", xts_type)
    root.add_children_by_paths(file_list)
    # 构建参与编译的目录树
    for name, c_node in list(root.children.items()):
        build_tree(c_node)
    # 构建的目录树打印
    # with open('out_build_tree_out_put.txt', 'w') as file:
    #     # json.dump(out_put, file, indent=4)
    #     build_tree_out_put = root.print_subtree()
    #     file.write(build_tree_out_put)
    # 未找到的节点打印
    # with open('out_not_find_path.txt', 'w') as file:
    #     json.dump(g_notfind_file, file, indent=4)
    # 扫描未参与编译的目录
    differences = []
    find_extra_directories(project_root, root, differences)
    # 待删除目录打印
    with open('out_file_differences.txt', 'w') as file:
        json.dump(differences, file, indent=4)

    # 将需删除的目录移动到out目录下
    if is_del:
        print('移动待删除目录至./out')
        move_differences(project_root, differences)
        print('移动完成')




if __name__ == '__test__':
    project_root = os.path.abspath("../xts_acts/multimedia")
    root = TreeNode(project_root, set(['multimedia']))
    build_tree(root)
    build_tree_out_put = root.print_subtree()
    with open('build_tree_out_put.txt', 'w') as file:
        # json.dump(out_put, file, indent=4)
        file.write(build_tree_out_put)
    build_tree_out_put = root.print_subtree()
    with open('build_tree_out_put.txt', 'w') as file:
        # json.dump(out_put, file, indent=4)
        file.write(build_tree_out_put)

    # 扫描未参与编译的目录
    differences = []
    find_extra_directories(project_root, root, differences)

    with open('file_differences.txt', 'w') as file:
        json.dump(differences, file, indent=4)